import {
  CloseCircleOutlined,
  CloseOutlined,
  PlusOutlined,
  StopOutlined,
  UploadOutlined,
} from '@ant-design/icons';
import { App, Divider, Progress, Spin } from 'antd';
import classNames from 'classnames';
import { isEmpty } from 'lodash-es';
import React, {
  createContext,
  memo,
  useContext,
  useMemo,
  useRef,
  useState,
} from 'react';
import TTUploader from 'tt-uploader';
import YmVideoPlayer from './YmVideoPlayer';
import {
  IUploadAuthTokenDetail,
  TFile,
  TStatus,
  YmUploadVideoProps,
} from './interface';
import { getAuthToken, getFileURL } from './utils/getAuthToken';

interface IVideUploadContext extends YmUploadVideoProps {
  url?: string;
  onRefreshContextValue?: (refreshParam: Record<string, any>) => void;
}

const VIDEUPLOADDIR = 'safeProject';
const VideUploadContext = createContext<IVideUploadContext>({});

type TViewVideoItem = TFile & {
  cardWidth: number;
  cardHeight: number;
  id: string;
};

function ViewVideoItem(props: TViewVideoItem) {
  const { vid, cardWidth, cardHeight, id, postUrl } = props;
  const { url, value, onChange, getPlayerAuthTokenApi } =
    useContext(VideUploadContext);
  const YmVideoPlayerConfig = {
    id,
    vid,
    width: cardWidth,
    height: cardHeight,
    url,
    postUrl,
    getPlayerAuthTokenApi,
  };
  return (
    <div className="view_box" style={{ width: cardWidth, height: cardHeight }}>
      <YmVideoPlayer {...YmVideoPlayerConfig} />
      <CloseCircleOutlined
        className="box_close"
        onClick={(e: React.MouseEvent) => {
          e.stopPropagation();
          let newValue;
          if (Array.isArray(value)) {
            newValue = value.filter((item) => item.vid !== vid);
          }
          //立马使用返回的Vid 获取playAuthToken，通过window.VePlayer()播放报错
          onChange?.(newValue);
        }}
      />
    </div>
  );
}

function ViewVideo() {
  const { value, cardHeight, cardWidth, id } = useContext(VideUploadContext);
  const fileList = value as Array<TFile>;
  return (
    <>
      {fileList.length > 0 &&
        fileList.map((item) => (
          <ViewVideoItem
            key={item.vid}
            {...item}
            cardWidth={cardWidth!}
            cardHeight={cardHeight!}
            id={id!}
          />
        ))}
    </>
  );
}

function UploadCard() {
  const {
    disabled,
    onChange,
    cardWidth,
    cardHeight,
    maxCount,
    label,
    required,
    accept,
    type,
    maxSize,
    // dir,
    multiple,
    children,
    userId,
    value,
    onRefreshContextValue,
    getUploadAuthTokenApi,
  } = useContext(VideUploadContext);
  const { message } = App.useApp();
  const fileRef = useRef<HTMLInputElement>(null);
  const [status, setStatus] = useState<TStatus>('initial');
  const [progressPercent, setProgressPercent] = useState(0);
  const [uploaderInstance, setUploaderInstance] = useState<TTUploader>();
  const [fileKey, setFileKey] = useState<string>();
  const [startOrPause, setStartOrPause] = useState('暂停');
  // input 多次上传同一个文件时，只会第一次触发onChange事件
  const clearInput = () => {
    if (fileRef.current && fileRef.current.value) {
      fileRef.current.value = '';
    }
  };

  const fileUpload = async (file: File) => {
    //1.获取临时凭证
    setStatus('preparing');
    const uploadAuthTokenDetail = (await getAuthToken(
      getUploadAuthTokenApi!,
    )) as IUploadAuthTokenDetail;
    if (isEmpty(uploadAuthTokenDetail)) {
      setStatus('initial');
      return message.error('获取playAuthToken失败！');
    }
    const {
      accessKeyId,
      currentTime,
      expiredTime,
      secretAccessKey,
      sessionToken,
    } = uploadAuthTokenDetail;
    const uploader = new TTUploader({
      userId: userId!,
      appId: 303103, //在视频点播-应用服务中创建的AppID，视频点播的质量监控等都是以这个参数来区分业务方的，务必正确填写
      // 仅视频/普通文件上传时需要配置
      videoConfig: {
        spaceName: 'safe', //在视频点播中申请的点播空间名
        processAction: [
          {
            name: 'GetMeta', //获取视频信息
          },
          {
            name: 'Snapshot', //取视频封面截图
            input: {
              SnapshotTime: 1.0, //截图时间
            },
          },
        ],
      },
    });
    setUploaderInstance(uploader);
    // const suffix = file.name.slice(file.name.lastIndexOf('.'));
    // const fileName = dir + '/' + Date.now() + suffix;
    const fileKey = uploader.addFile({
      file,
      stsToken: {
        AccessKeyId: accessKeyId,
        SecretAccessKey: secretAccessKey,
        SessionToken: sessionToken,
        ExpiredTime: expiredTime,
        CurrentTime: currentTime,
      },
      type: 'video', // 上传文件类型，三个可选值：video(视频或者音频，默认值)，image(图片)，object（普通文件）
      // fileName,
    });
    setFileKey(fileKey);
    uploader.start(fileKey);
    uploader.on('progress', (infor: any) => {
      // console.log('--progress--infor--:', infor);
      setStatus('uploading');
      setProgressPercent(infor.percent);
    });
    uploader.on('complete', (infor: any) => {
      console.log('--complete--infor--:', infor);
      const host = location.protocol === 'https:' ? 'https:' : 'http:';
      const postUrl =
        host +
        '//hsimg.logibeat.com/' +
        infor.uploadResult.PosterUri +
        '~tplv-vod-obj.jpeg';
      const vid = infor.uploadResult.Vid;
      const fileName = infor.fileName || '';
      let newValue;
      if (Array.isArray(value)) {
        value.push({ vid, postUrl, fileName });
        newValue = value.filter((item, index, self) => {
          return (
            self.findIndex((selfItem) => selfItem.vid === item.vid) === index
          );
        });
      } else {
        newValue = { vid, postUrl, fileName };
        console.log('---complete--newValue---:', newValue);
      }
      //立马使用返回的Vid 获取playAuthToken，通过window.VePlayer()播放报错
      onChange?.(newValue, infor);
      // setTimeout(() => {
      //   onChange?.(newValue);
      // }, 10000);
      // 改为用url播放
      onRefreshContextValue?.({ url: getFileURL(file) });
      setStatus('complete');
      clearInput();
    });
    uploader.on('error', (infor: any) => {
      console.log('--error--infor--:', infor);
      setStatus('error');
      clearInput();
    });
  };

  const beforeUpload: React.ChangeEventHandler<HTMLInputElement> = (event) => {
    if (!event.target.files || disabled) return;
    const files = event.target.files;
    // console.log('--beforeUpload--files--typeof files--:', files, Array.isArray(files)); // 不是数组 是对象{0:File,1:File}
    for (let i = 0; i < files.length; i++) {
      const file = files.item(i);
      if (file) {
        // console.log('---beforeUpload--file--:', file);
        const suffix = file.name.replace(/.*\./, '').toLowerCase();
        // console.log('--beforeUpload--suffix--:', suffix);
        if (!type!.includes(suffix)) {
          const content = type?.join('、');
          clearInput();
          return message.warning(
            `视频上传失败！仅支持【${content}！】格式！`,
            1.5,
          );
        }
        if (file.size / 1024 / 1024 / 1024 > maxSize! / 1024) {
          clearInput();
          return message.warning(
            `文件上传失败！附件大小不能超过${maxSize! / 1024}G！`,
            1.5,
          );
        }
        fileUpload(file);
      }
    }
  };

  const config = {
    type: disabled ? 'hidden' : 'file',
    disabled,
    accept,
    title: '',
    multiple,
    className: 'upload_input',
    onChange: beforeUpload,
  };

  // 未上传时的占位符
  const UploadPlaceholder = () => (
    <>
      {maxCount === 1 ? (
        <UploadOutlined style={{ fontSize: 24 }} />
      ) : (
        <PlusOutlined style={{ fontSize: 24 }} />
      )}
      {label && (
        <p style={{ marginTop: 8 }}>
          {required && <span style={{ color: '#FD4D4E' }}>*</span>}
          {label}
        </p>
      )}
    </>
  );

  const carBoxItem = useMemo(() => {
    if (status === 'initial' || status === 'complete') {
      return (
        <div className="card_box_item item_initial">
          <input ref={fileRef} {...config} />
          {children || <UploadPlaceholder />}
        </div>
      );
    } else if (status === 'preparing') {
      return (
        <Spin spinning>
          <div
            className="card_box_item item_preparing"
            style={{ width: cardWidth, height: cardHeight }}
          ></div>
        </Spin>
      );
    } else if (status === 'uploading') {
      return (
        <div className="card_box_item item_uploading">
          <Progress
            type="circle"
            percent={progressPercent}
            size={70}
            strokeColor="#f66e2c"
          />
          <div className="uploading_operation">
            <span
              className="operation_item"
              onClick={(e: React.MouseEvent) => {
                e.stopPropagation();
                if (fileKey) {
                  setStatus('initial');
                  uploaderInstance?.cancel(fileKey); //未传参数fileKey, 取消所有文件的上传}
                }
              }}
            >
              <CloseOutlined className="item_icon" />
              取消
            </span>
            <Divider
              type="vertical"
              style={{ backgroundColor: 'rgb(102, 102, 102)' }}
            ></Divider>
            <span
              className="operation_item"
              onClick={(e: React.MouseEvent) => {
                e.stopPropagation();

                if (fileKey) {
                  if (startOrPause === '暂停') {
                    uploaderInstance?.pause(fileKey);
                    setStartOrPause('继续上传');
                  } else {
                    uploaderInstance?.start(fileKey);
                    setStartOrPause('暂停');
                  }
                }
              }}
            >
              {startOrPause === '暂停' ? (
                <StopOutlined className="item_icon" />
              ) : (
                <UploadOutlined className="item_icon" />
              )}

              {startOrPause}
            </span>
          </div>
        </div>
      );
    } else if (status === 'error') {
      return (
        <div className="card_box_item item_uploading">
          <Progress
            type="circle"
            percent={progressPercent}
            size={70}
            status="exception"
          />
          <div className="uploading_operation">
            <span className="operation_item">
              <UploadOutlined className="item_icon" />
              重新上传
            </span>
          </div>
          <input ref={fileRef} {...config} />
        </div>
      );
    }
  }, [
    status,
    progressPercent,
    uploaderInstance,
    fileKey,
    startOrPause,
    maxCount,
  ]);

  return (
    <div
      className={classNames('upload_card_box', { disabled: disabled })}
      style={{ height: cardHeight, width: cardWidth }}
    >
      {carBoxItem}
    </div>
  );
}

const YmVideoUpload: React.FC<YmUploadVideoProps> = (props) => {
  const defaultConfig = {
    cardWidth: 300,
    cardHeight: 150,
    label: '上传视频',
    type: [
      'mp4',
      'flv',
      'asf',
      'rm',
      'rmvb',
      'mpeg',
      'mov',
      'avi',
      'flash',
      'mpegts',
      'm4s',
      'm3u8',
      'matroska',
      'wmv',
      '3gp',
      'ts',
      'mpg',
      'webm',
      'mkv',
      'wm',
      'asx',
      'ram',
      'mpe',
      'vob',
      'dat',
      'mp4v',
      'm4v',
      'f4v',
      'mxf',
      'qt',
    ],
    maxSize: 2048, //以M为单位 2G
    dir: VIDEUPLOADDIR,
    accept: 'video/*',
    required: false,
    multiple: false,
    id: 'ym_video',
    userId: 'unknownUser',
    maxCount: 1,
  };

  const handlRefreshContextValue = (refreshParam: any) => {
    // eslint-disable-next-line @typescript-eslint/no-use-before-define
    setContextValue((prev) => ({ ...prev, ...refreshParam }));
  };

  const { value, warningChildren, hideWarningChildren = false } = props;
  const [contextValue, setContextValue] = useState<IVideUploadContext>({
    ...defaultConfig,
    ...props,
    onRefreshContextValue: handlRefreshContextValue,
  });

  const Control = () => {
    if (Array.isArray(value)) {
      return (
        <>
          {<ViewVideo />}
          {value.length < defaultConfig.maxCount ? <UploadCard /> : null}
        </>
      );
    } else {
      return (
        <>
          {value && !isEmpty(value) ? (
            <ViewVideoItem
              {...value}
              cardWidth={contextValue.cardWidth!}
              cardHeight={contextValue.cardHeight!}
              id={contextValue.id!}
            />
          ) : (
            <UploadCard />
          )}
        </>
      );
    }
  };

  const finalWarningChildren = useMemo(
    () =>
      React.isValidElement(warningChildren) ? (
        warningChildren
      ) : hideWarningChildren ? null : (
        <div className="upload_warning">
          <p>温馨提示：</p>
          <ul>
            <li>1、支持所有视频格式；</li>
            <li>2、视频大小不超过 2G；</li>
            <li>
              3、
              不可以发布涉黄、涉毒、色情等违反法律规定的视频，一切后果由发布人承担；
            </li>
          </ul>
        </div>
      ),
    [warningChildren, hideWarningChildren],
  );

  return (
    <VideUploadContext.Provider value={contextValue}>
      <div className="safe_edu_upload">
        {Control()}
        {finalWarningChildren}
      </div>
    </VideUploadContext.Provider>
  );
};

export default memo(YmVideoUpload);
